package com.tarzan.cms.modules.admin.service.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tarzan.cms.common.constant.CoreConst;
import com.tarzan.cms.modules.admin.mapper.biz.ArticleMapper;
import com.tarzan.cms.modules.admin.model.biz.*;
import com.tarzan.cms.modules.admin.vo.ArticleConditionVo;
import com.tarzan.cms.modules.admin.vo.TimelineVO;
import com.tarzan.cms.utils.DateUtil;
import com.tarzan.cms.utils.WebUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tarzan liu
 * @since JDK1.8
 * @date 2021年5月11日
 */
@Service
@AllArgsConstructor
public class ArticleService extends ServiceImpl<ArticleMapper, Article> {

    private final ArticleLookService articleLookService;
    private final LoveService loveService;
    private final CommentService commentService;
    private final ArticleTagsService articleTagsService;
    private final TagsService tagsService;

    public List<Article> findByCondition(IPage<Article> page, ArticleConditionVo vo) {
        return baseMapper.findByCondition(page, vo);
    }

    @Cacheable(value = "article", key = "'slider'")
    public List<Article> sliderList() {
        return super.lambdaQuery().select(Article::getId,Article::getCoverImage,Article::getTitle)
                .eq(Article::getStatus,CoreConst.STATUS_VALID).eq(Article::getSlider,CoreConst.STATUS_VALID).list();
    }

    @Cacheable(value = "article", key = "'recommended'")
    public List<Article> recommendedList(int pageSize) {
        ArticleConditionVo vo = new ArticleConditionVo();
        vo.setRecommended(true);
        vo.setStatus(CoreConst.STATUS_VALID);
        vo.setPageSize(pageSize);
        IPage<Article> page = new Page<>(vo.getPageNumber(), vo.getPageSize());
        return this.findByCondition(page, vo);
    }

    @Cacheable(value = "article", key = "'recent'")
    public List<Article> recentList(int pageSize) {
        ArticleConditionVo vo = new ArticleConditionVo();
        vo.setRecentFlag(true);
        vo.setStatus(CoreConst.STATUS_VALID);
        vo.setPageSize(pageSize);
        IPage<Article> page = new Page<>(vo.getPageNumber(), vo.getPageSize());
        return this.findByCondition(page, vo);
    }

    @Cacheable(value = "article", key = "'random'")
    public List<Article> randomList(int pageSize) {
        LambdaQueryWrapper<Article> wrapper=Wrappers.lambdaQuery();
        wrapper.eq(Article::getStatus,CoreConst.STATUS_VALID);
        long count=super.count(wrapper);
        long index= RandomUtils.nextLong(0,(count-pageSize));
        wrapper.last("limit "+index+","+pageSize);
        return super.list(wrapper);
    }

    @Cacheable(value = "article", key = "'hot'")
    public List<Article> hotList(int pageSize) {
        IPage<Article> page = new Page<>(1, pageSize);
        return baseMapper.hotList(page);
    }

    public Article readById(Integer id) {
        Article article=getById(id);
        if(article==null){
            return new Article();
        }
        List<Tags> aTags = new ArrayList<>(3);
        List<ArticleTags> articleTagsList=articleTagsService.lambdaQuery().eq(ArticleTags::getArticleId,id).list();
        if(CollectionUtils.isNotEmpty(articleTagsList)){
            List<Integer> tagsIds=articleTagsList.stream().map(ArticleTags::getTagId).collect(Collectors.toList());
            aTags = tagsService.listByIds(tagsIds);
        }
        article.setTags(aTags);
        long lookNum=articleLookService.count(Wrappers.<ArticleLook>lambdaQuery().eq(ArticleLook::getArticleId,id));
        article.setLookCount(lookNum);
        long loveNum=loveService.count(Wrappers.<Love>lambdaQuery().eq(Love::getBizId,id).eq(Love::getBizType,1));
        article.setLoveCount(loveNum);
        long commentNum= commentService.count(Wrappers.<Comment>lambdaQuery().eq(Comment::getSid,id));
        article.setCommentCount(commentNum);
        articleLookService.look(id);
        return article;
    }


    @Override
    @Cacheable(value = "article", key = "'count'")
    public long count() {
        return count(Wrappers.<Article>lambdaQuery().eq(Article::getStatus, CoreConst.STATUS_VALID));
    }

    @Cacheable(value = "article", key = "'timeline'")
    public List<TimelineVO> timeline() {
        List<TimelineVO> list=new ArrayList<>(3);
        List<Article> articles=list(Wrappers.<Article>lambdaQuery().select(Article::getId,Article::getTitle,Article::getCreateTime).eq(Article::getStatus, CoreConst.STATUS_VALID));
        Map<String,List<Article>>  map= articles.stream().collect(Collectors.groupingBy(e-> DateUtil.format(e.getCreateTime(),"yyyy年")));
        map.forEach((k,v)->{
            TimelineVO vo=new TimelineVO();
            vo.setYear(k);
            vo.setArticles(v);
            list.add(vo);
        });
       return  list;
    }

    @CacheEvict(value = "article", allEntries = true)
    public Article insertArticle(Article bizArticle) {
        Date date = new Date();
        bizArticle.setCreateTime(date);
        bizArticle.setUpdateTime(date);
        save(bizArticle);
        return bizArticle;
    }

    public List<Article> selectByCategoryId(Integer categoryId) {
        return list(Wrappers.<Article>lambdaQuery().eq(Article::getCategoryId, categoryId));
    }

    @CacheEvict(value = "article", allEntries = true)
    public boolean deleteBatch(List<Integer> ids){
        return removeByIds(ids);
    }


}
